/*
 * Script that contains the pseudo-class definition
 * for a DecisionLines choice
 * 
 * Author: Chris Casola
 */

(function() {

	/**
	 * Represents a Choice in a DecisionLines event
	 */
	function Choice(choicePosition) {
		
		/** Label for this Choice */
		this.label = "";
		
		/** The position of this Choice */
		this.position = choicePosition;
		
		/** List of Edges connected to the left side of this Choice */
		this.leftEdges = new Array();
		
		/** List of Edges connected to the right side of this Choice */
		this.rightEdges = new Array();
		
		/** Last retrieved edge side */
		this.side = "";
		
		/**
		 * Adds an Edge to this Choice
		 * 
		 * @param vPos the vertical position of the Edge
		 * @param side the side of this choice the Edge is attached to, must be one of "left" or "right"
		 */
		this.addEdge = function (vPos, side) {
			var theList = [];
			if (side == "left") {
				theList = this.leftEdges;
			}
			else if (side == "right") {
				theList = this.rightEdges;
			}
			else {
				throw "InvalidSide";
			}
			
			// Add the new Edge to the list in sorted position
			insertEdgeSorted(theList, new Edge(vPos));
		};
		
		/**
		 * Gets the next closest Edge with a position less
		 * than the given vertical position
		 */
		this.getPrevEdge = function (vPos) {
			var leftEdge = getPrevEdgeInList(vPos, this.leftEdges); // get the next closest left edge
			var rightEdge = getPrevEdgeInList(vPos, this.rightEdges); // get the next closest right edge
			
			// If there are no edges less than the given position return null
			if ((leftEdge == null) && (rightEdge == null)) {
				return null;
			}
			else if (leftEdge == null) { // There is no left edge, so return the right edge
				return rightEdge;
			}
			else if (rightEdge == null) { // There is no right edges, so return the left edge
				return leftEdge;
			}
			else { // There is a left and right edge, so return the one that is closest to the given vertical position
				if (leftEdge.vPos > rightEdge.vPos) {
					return leftEdge;
				}
				else {
					return rightEdge;
				}
			}
		};
		
		/**
		 * Gets the next closest Edge with a position greater
		 * than the given vertical position.  Sets the value of the
		 * side field so that a call to the getSide() method can return
		 * the side of the last edge retrieved using the getNextEdge() method.
		 */
		this.getNextEdge = function (vPos) {
			var leftEdge = getNextEdgeInList(vPos, this.leftEdges); // get the next closest left edge
			var rightEdge = getNextEdgeInList(vPos, this.rightEdges); // get the next closest right edge
			
			// If there are no edges greater than the given vertical position return null
			if ((leftEdge == null) && (rightEdge == null)) {
				return null;
			}
			else if (leftEdge == null) { // There is no left edge, so return the right edge
				this.side = "right";
				return rightEdge;
			}
			else if (rightEdge == null) { // There is no right edges, so return the left edge
				this.side = "left";
				return leftEdge;
			}
			else { // There is a left and right edge, so return the one that is closest to the given vertical position
				if (leftEdge.vPos < rightEdge.vPos) {
					this.side = "left";
					return leftEdge;
				}
				else {
					this.side = "right";
					return rightEdge;
				}
			}
		};
		
		/**
		 * Returns the next edge above the given vertical position in
		 * the given list of Edges
		 */
		function getPrevEdgeInList(vPos, theList) {
			for (var i = theList.length - 1; i >= 0; i--) {
				if (theList[i].vPos < vPos) {
					return theList[i];
				}
			}
			return null; /* No edges have a smaller vPos than the position given */
		}
		
		/**
		 * Returns the next edge below the given vertical position in
		 * the given list of Edges
		 */
		function getNextEdgeInList(vPos, theList) {
			for (var i=0; i < theList.length; i++) {
				if (theList[i].vPos > vPos) {
					return theList[i];
				}
			}
			return null; /* No edges have a greater vPos than the position given */
		}
		
		/**
		 * Inserts the given Edge into the given list in sorted
		 * order by vertical position.
		 */
		function insertEdgeSorted(theList, theEdge) {
			for (var i = 0; i < theList.length; i++) {
				if (theEdge.vPos < theList[i].vPos) {
					theList.splice(i, 0, theEdge);
					return;
				}
			}
			theList.push(theEdge);
		}
	}
	window.Choice = Choice;
}).call();
